1. Vulnerability Background
This set of fixes addresses multiple security weaknesses in curl/libcurl and associated tooling. The patched issues include:
- cross-scheme proxy credential leakage during redirects
- asynchronous DNS-over-HTTPS (DoH) probe completion use-after-free
- thread-safety/race condition in shared handle state
- unbounded HSTS cache growth leading to resource exhaustion
- allocator mismatch / invalid free in tool parameter handling
- improper file descriptor initialization leading to accidental closure
- command injection risk in a test harness invocation
Why this is important:
- curl/libcurl is a widely deployed library used by browsers, clients, embedded systems, and tooling.
- vulnerabilities in core path handling, async resolution, and proxy behavior can expose sensitive data, destabilize applications, or create memory corruption conditions.
- because these issues affect network-facing or multi-threaded code, they can be exploited by remote servers or local attackers controlling input or responses.
Affected systems/versions:
- curl/libcurl versions prior to the 2026 patch cycle corresponding to CVE-2026-5545, CVE-2026-5773, CVE-2026-6253, CVE-2026-6429, and CVE-2026-7168.
- any build configured with HSTS, DoH, proxy redirect handling, shared handles, or the affected tool options.
2. Technical Details
Root cause analysis
-
Proxy credential leakage
- The regression test addition indicates a vulnerability in redirect handling when proxy credentials are present in
http_proxyand--location-trustedis enabled. - The code path allowed proxy authorization to be reused across a cross-scheme redirect, potentially leaking credentials to an unintended destination.
- The regression test addition indicates a vulnerability in redirect handling when proxy credentials are present in
-
DoH asynchronous completion use-after-free
- In
lib/doh.c,doh_probe_done()dereferenceddata->state.async.dohand metadata fromCurl_meta_get(doh, CURL_EZM_DOH_PROBE)without ensuring the async context was still valid. - If the original async resolver had been freed or the DoH probe delayed, the callback could act on stale memory.
- In
-
Thread safety race in shared handles
lib/curl_share.hstored avolatile unsigned int dirtyand hadhas_been_sharedstate with no proper locking.- Concurrent access to shared handle state could lead to races, memory corruption, or invalid reference counting.
-
HSTS cache exhaustion
lib/hsts.hlacked an upper bound for HSTS entries.- A remote peer could cause libcurl to consume unbounded memory by sending many unique
Strict-Transport-Securityheaders.
-
Heap allocator mismatch in tool code
src/tool_getparam.cassignedcurl_maprintf()output directly intoconfig->ech_configwhile later code paths expected memory allocated with thecurlx_allocator family.- This mismatch can lead to invalid frees or heap corruption.
-
Improper file descriptor initialization
lib/file.callocatedfilepwithout initializingfilep->fd.- The destructor could close an uninitialized descriptor, potentially closing STDIN or another unrelated handle.
-
Test harness shell injection
tests/test1276.plusedopen(my $fh, "-|", "perl $root/lib/optiontable.pl < $root/include/curl/curl.h");via a shell command string.- If
rootwere attacker-controllable, this would allow arbitrary shell invocation.
Attack vector and exploitation conditions
- Proxy credential leakage: attacker-controlled redirect target or proxy configuration may cause authorization headers to be forwarded improperly.
- DoH use-after-free: asynchronous DoH resolution with delayed responses and concurrent cleanup.
- Shared handle race: multi-threaded use of
CURLSHhandles combined with concurrent transfer creation/cleanup. - HSTS exhaustion: repeated navigation to unique hosts that send HSTS instructions.
- Allocator mismatch: configuration parsing triggered by user-supplied options causing allocations and frees across API boundaries.
- File descriptor issue: local error path when a file transfer object is created and subsequently destroyed.
- Shell injection: malicious path in test environment or build scripts.
Security implications
- Credential leakage to untrusted endpoints or proxies.
- Memory corruption leading to crashes or potential code execution.
- Denial-of-service via resource exhaustion.
- Reliability issues in applications using shared handles or asynchronous DNS resolution.
- Local privilege escalation or data exposure in test/build environments.
3. Patch Analysis
What code changes were made
-
tests/test1276.pl- Old:
open(my $fh, "-|", "perl $root/lib/optiontable.pl < $root/include/curl/curl.h"); - Fixed:
open(my $fh, "-|", 'perl', "$root/lib/optiontable.pl", "$root/include/curl/curl.h"); - Change: use exec list form to avoid shell parsing and redirection.
- Old:
-
lib/curl_share.h- Added
#include "curl_threads.h" - Added explicit
uint32_t ref_count - Added
curl_mutex_t lockandint has_been_sharedunderUSE_MUTEX - Otherwise
volatile int has_been_shared - Change: explicit thread synchronization state and reference counting.
- Added
-
lib/hsts.h- Added
#define MAX_HSTS_ENTRIES 10000 - Change: upper bound HSTS cache size.
- Added
-
lib/doh.c- Reworked
doh_probe_done()to:- fetch
doh_reqfirst - bail out if
doh_reqis missing - validate existence of
Curl_async_get(data, doh_req->resolv_id) - ignore outdated DoH responses
- remove metadata only after use
- fetch
- Change: robust validation of async state before memory access.
- Reworked
-
src/tool_getparam.c- Old: assign
curl_maprintf()output directly toconfig->ech_config - Fixed: allocate
tmpwithcurl_maprintf(), freetmpcfg, duplicate withcurlx_strdup(tmp), freetmpwithcurl_free() - Change: allocator-family consistent ownership and free semantics.
- Old: assign
-
lib/file.c- Added
filep->fd = -1;after successful allocation. - Change: sentinel initialization prevents accidental descriptor closure.
- Added
-
docs/libcurl/opts/CURLOPT_HTTPPROXYTUNNEL.md- Added
CURLcode result;andcurl_easy_cleanup(curl); - Change: proper resource cleanup in example.
- Added
-
tests/data/test2011- Added regression case covering proxy credential handling during cross-scheme redirect with trusted location.
- Change: ensures future changes do not reintroduce the leakage.
How the changes fix the vulnerability
openlist form eliminates shell injection by avoiding a shell interpreter entirely.- explicit refcount/lock data ensures
Curl_sharestate is updated atomically and consistently across threads. - bounding HSTS entries prevents untrusted servers from exhausting memory.
doh_probe_done()now ignores stale completions and avoids dereferencing freed/invalid async context.- allocator symmetry removes a class of invalid free issues that can lead to heap corruption.
- initializing
filep->fdensures the destructor only closes valid handles. - improved documentation and regression tests reinforce safe usage and prevent reintroduction.
Security improvements introduced
- hardened async and multithreaded code paths.
- stronger defensive coding in client-side resolver and proxy handling.
- explicit resource limits for cache state.
- better memory allocator discipline.
- regression coverage for credential exposure scenarios.
4. Proof of Concept (PoC) Guide
Prerequisites for exploitation
- A vulnerable curl/libcurl build prior to the patch.
- For proxy credential leakage: environment with
http_proxycontaining credentials, a server returning a cross-scheme redirect, and--location-trustedenabled. - For DoH use-after-free: a DoH-capable configuration and the ability to force delayed async responses.
- For HSTS exhaustion: a server that can issue many
Strict-Transport-Securityheaders for many hostnames. - For shared-handle race: a multithreaded client using
CURLSHconcurrently.
Step-by-step exploitation approach
-
Proxy credential leakage
- Set
http_proxy=http://user:[email protected]:8080 - Run curl against
http://victim.example/with--location-trusted - Have the server respond with:
HTTP/1.1 301 Moved PermanentlyLocation: https://another.example/
- Capture the proxy request stream and check if
Proxy-Authorizationis sent toanother.exampleor on the CONNECT request. - Vulnerable behavior: proxy credentials are forwarded to the redirected destination.
- Patched behavior: credentials are not leaked beyond the authorized proxy context.
- Set
-
HSTS exhaustion
- Configure a test server to respond with
Strict-Transport-Security: max-age=31536000 - Perform requests to many distinct hostnames or unique
Host:values. - Monitor memory use or HSTS list length.
- Vulnerable behavior: the internal HSTS cache grows without bound.
- Patched behavior: insertion stops or evicts entries once
MAX_HSTS_ENTRIESis reached.
- Configure a test server to respond with
-
DoH use-after-free
- Trigger async DoH resolution via libcurl option paths that use the probe machinery.
- Simulate a delayed DoH response arriving after the original async resolver has been cleaned up.
- Vulnerable behavior:
doh_probe_done()dereferences staledohpordoh_req, potentially crashing. - Patched behavior: the callback detects outdated state and returns safely.
-
Shared handle race
- Create a
CURLSHhandle and perform many concurrent transfers from multiple threads. - Use thread sanitizer or stress test to observe race failures.
- Vulnerable behavior: shared handle internal state becomes inconsistent or crashes.
- Patched behavior: shared handle state is guarded by lock/refcount semantics.
- Create a
Expected behavior vs exploited behavior
- Expected: no credential leakage, no stale async access, bounded cache size, no descriptor misclosure, no allocator mismatch.
- Exploited: unauthorized forwarding of proxy auth, memory corruption/crash from use-after-free, unbounded memory consumption, accidental closure of STDIN, heap corruption.
How to verify the vulnerability exists
- Reproduce using regression-style tests or minimal scripts.
- For proxy leakage, verify the presence of leaked
Proxy-Authorizationon redirected requests. - For DoH, trigger the callback path with stale async state and confirm a crash or assertion.
- For HSTS, observe the growth of the HSTS entry list beyond reasonable limits.
- For the allocator bug, audit free paths or run with runtime checks such as ASAN and observe invalid free warnings.
- Use the newly added regression test
tests/data/test2011as a canonical verification for the proxy leakage fix.
5. Recommendations
Mitigation strategies
- Upgrade to the patched curl/libcurl release that contains these fixes.
- Rebuild applications against the patched library version.
- For deployments using proxies and redirects, avoid enabling
--location-trustedunless necessary. - Limit HSTS cache growth in environments where untrusted hosts may be encountered.
Detection methods
- Network inspection for unexpected
Proxy-Authorizationheaders after redirects. - Runtime sanitizer use:
- AddressSanitizer (ASAN) for use-after-free and invalid memory access.
- ThreadSanitizer (TSAN) for shared handle races.
- Valgrind or heap-checking tools for allocator mismatches.
- Fuzzing DoH and proxy redirect handling code paths.
- Static analysis for shell invocation and allocator family consistency.
Best practices to prevent similar issues
- Avoid shell command strings and use argument lists for external process execution.
- Initialize all structure fields, especially descriptor and pointer members.
- Keep allocator and deallocator families consistent.
- Enforce explicit bounds on caches and resource stores.
- Validate async callback state before using context pointers.
- Protect shared mutable state with proper synchronization primitives.
- Add regression tests for security-sensitive behaviors, including redirect and proxy handling.
- Treat documentation examples as executable code and include cleanup paths.
These patches strengthen curl/libcurl by closing both functional and security gaps in async resolution, shared state, resource management, and credential handling.